import java.awt.*;
import java.awt.geom.*;
import java.util.*;


/**
 * @author Andy
 */
public class Player extends Entity {
       
        private static final int FACTOR = 100;
        PlayerCollider collider;
        protected Direction curDirection;
        protected int bombCnt, bombsDown;
        protected int speed;
        protected int maxSpeed;
        final String[] textures = new String[]{"front1.png", "front2.png", "front3.png", // 0 1 2
                           "left1.png", "left2.png", "left3.png",    // 3 4 5
                           "right1.png", "right2.png", "right3.png", // 6 7 8
                           "back1.png", "back2.png", "back3.png"};   // 9 10 11
        final String[] prefixes = new String[]{"Resources/fronts/", // 0
                           "Resources/lefts/",  // 1
                           "Resources/rights/", // 2
                           "Resources/backs/"}; // 3
        public Player(int x, int y)
        {
                super.setPosition(x, y);
                speed = 1;
                maxSpeed = 2;
                bombCnt = 3;
                bombsDown = 0;
                setSize(60,60);
                this.bounds = new Rectangle(0,0,30,30);
                collider = new PlayerCollider(this);
                collider.<Player>register(Player.class, "onPlayerHit");                                    
                texture = ResourceManager.getManager().load(prefixes[1] + textures[3]);
                curDirection = Direction.Down;
        }
       
        public void onPlayerHit(Player player)
        {
                //nothing to handle currently
        }
       
       
        /**
         * Moves player in specified direction at max speed.
         * The player will continue to move until stop() is called.
         * @param direction Up,Down,Left,Right
         */
        public void move(Direction direction)
        {
                move(direction,maxSpeed);
        }
        public void move(Direction direction,int speed)
        {
                this.speed = speed > maxSpeed? maxSpeed:speed;
               
                if(direction == Direction.Left) {
                        velocity = new Point2D.Double(-1,0);
                       
                        if((this.getPosition().x % FACTOR) < 25)
                                texture = ResourceManager.getManager().load(prefixes[1] + textures[3]);
                        else if((this.getPosition().x % FACTOR) >= 25 && this.getPosition().x % FACTOR <= 50)
                                texture = ResourceManager.getManager().load(prefixes[1] + textures[4]);
                        else if((this.getPosition().x % FACTOR > 50 && this.getPosition().x % FACTOR <= 75))
                                texture = ResourceManager.getManager().load(prefixes[1] + textures[3]);
                        else if((this.getPosition().x % FACTOR > 75))
                                texture = ResourceManager.getManager().load(prefixes[1] + textures[5]);
                       
                }
                else if(direction == Direction.Right) {
                        velocity = new Point2D.Double(1,0);
                       
                        if((this.getPosition().x % FACTOR) < 25)
                                texture = ResourceManager.getManager().load(prefixes[2] + textures[6]);
                        else if((this.getPosition().x % FACTOR) >= 25 && this.getPosition().x % FACTOR <= 50)
                                texture = ResourceManager.getManager().load(prefixes[2] + textures[7]);
                        else if((this.getPosition().x % FACTOR > 50 && this.getPosition().x % FACTOR <= 75))
                                texture = ResourceManager.getManager().load(prefixes[2] + textures[6]);
                        else if((this.getPosition().x % FACTOR > 75))
                                texture = ResourceManager.getManager().load(prefixes[2] + textures[8]);
                }
                else if(direction == Direction.Up) {
                        velocity = new Point2D.Double(0,-1);
                       
                        if((this.getPosition().y % FACTOR) < 25)
                                texture = ResourceManager.getManager().load(prefixes[3] + textures[9]);
                        else if((this.getPosition().y % FACTOR) >= 25 && this.getPosition().y % FACTOR <= 50)
                                texture = ResourceManager.getManager().load(prefixes[3] + textures[10]);
                        else if((this.getPosition().y % FACTOR > 50 && this.getPosition().y % FACTOR <= 75))
                                texture = ResourceManager.getManager().load(prefixes[3] + textures[9]);
                        else if((this.getPosition().y % FACTOR > 75))
                                texture = ResourceManager.getManager().load(prefixes[3] + textures[11]);
                }
                else if(direction == Direction.Down) {
                        velocity = new Point2D.Double(0,1);
                       
                        if((this.getPosition().y % FACTOR) < 25)
                                texture = ResourceManager.getManager().load(prefixes[0] + textures[0]);
                        else if((this.getPosition().y % FACTOR) >= 25 && this.getPosition().y % FACTOR <= 50)
                                texture = ResourceManager.getManager().load(prefixes[0] + textures[1]);
                        else if((this.getPosition().y % FACTOR > 50 && this.getPosition().y % FACTOR <= 75))
                                texture = ResourceManager.getManager().load(prefixes[0] + textures[0]);
                        else if((this.getPosition().y % FACTOR > 75))
                                texture = ResourceManager.getManager().load(prefixes[0] + textures[2]);
                        }
       
                curDirection = direction;
        }
       
        public void stop()
        {
                speed = 0;
        }
       
       
        public void dropBomb() {
               
                if(bombsDown < bombCnt) {
                       
                        Bomb bomb = new Bomb(this.position.x, this.position.y);
                        manager.addEntity(bomb);
                        bombsDown++;
                       
                }
        }
        public void update(float dt)
        {
                if(!collider.checkCollisions())
                {
                        getPosition().x = (int)Math.round(getPosition().x + this.velocity.getX() * (speed * dt));
                        getPosition().y = (int)Math.round(getPosition().y + this.velocity.getY() * (speed * dt));
                }
        }
       
        public void draw(Graphics2D g)
        {
                super.draw(g);
        }
       
        public int getSpeed()
        {
                return speed;
        }
       
        /**
         * Class checks for collisions for moving player objects.
         *  One bug I know of is that after the collision the player
         *  does not move to the closest point that it can move too.
         *  Although this is only for high speeds so we shouldnt have
         *  to worry about it.
         * @author Andy
         *
         */
        class PlayerCollider extends Collider<Player>
        {
                public PlayerCollider(Player owner)
                {
                        super(owner);
                }
               
                public boolean checkCollisions()
                {
                        Rectangle moveBounds = getMoveRectangle();
                        java.util.List<Entity> colliders = null;
                       
                        colliders = owner.getManager().getEntitys(EntityManager.Filters.allWithin(moveBounds));
                       
                        for(Entity entity : colliders)
                                if(owner != entity)
                                {
                                  entity.collider.fireEvent(owner, entity); //notify other party member
                                  this.fireEvent(owner, entity);
                                }

                        return (colliders.size() > 1); //your self will be included so greater than 1
                }
                /**
                 * Retrieves a rectangle encompassing where the player started to the place where it will end up.
                 */
                private Rectangle getMoveRectangle()
                {
                       
                        Point nextPos = new Point();
                        nextPos.x = (int)(owner.getPosition().x + owner.getVelocity().x * owner.getSpeed());
                        nextPos.y = (int)(owner.getPosition().y + owner.getVelocity().y * owner.getSpeed());
                       
                        Rectangle moveBounds = new Rectangle();
               
                        int minX = Math.min(nextPos.x, owner.getPosition().x);
                        int minY = Math.min(nextPos.y, owner.getPosition().y);
                        int maxX = Math.max(nextPos.x, owner.getPosition().x);
                        int maxY = Math.max(nextPos.y, owner.getPosition().y);
                        maxX += owner.getSize().x;
                        maxY += owner.getSize().y;
                        moveBounds.x = minX;
                        moveBounds.y = minY;
                        moveBounds.width = maxX - minX;
                        moveBounds.height = maxY - minY;
                        return moveBounds;
                }
        }
       
        enum Direction
        {
                Left,
                Right,
                Up,
                Down,
        }



}
